#include "tdlg.h"
#include "tapp.h"

TDlg::TDlg( UINT resId, TWin* parent )
: TWin( parent )
, _resId( resId )
, _modalFlg( FALSE )
, _maxItems( 0 )
, _dlgItems( NULL )
{
}

TDlg::~TDlg()
{
	if( _hWnd ) EndDialog( FALSE );
	delete[] _dlgItems;
}

BOOL TDlg::Create( HINSTANCE hI /* = NULL */ )
{
	TApp::GetApp()->AddWin( this );
	_hWnd = TAPI32V::CreateDialogV( hI ? hI : TApp::GetInstance(), (void*)_resId, 
		_parent ? _parent->_hWnd : NULL, (DLGPROC)TApp::WinProc );
	if( _hWnd ) return TRUE;
	TApp::GetApp()->DelWin( this );
	return FALSE;
}

int TDlg::Exec()
{
	TApp::GetApp()->AddWin( this );
	_modalFlg = TRUE;
	int result = TAPI32V::DialogBoxV( TApp::GetInstance(), (void*)_resId, _parent ? _parent->_hWnd : NULL,
		(DLGPROC)TApp::WinProc );
	_modalFlg = FALSE;
	return result;
}

void TDlg::Destroy()
{
	EndDialog( FALSE );
}

LRESULT TDlg::WinProc( UINT uMsg, WPARAM wParam, LPARAM lParam )
{
	LRESULT result = 0;
	switch( uMsg )
	{
	case WM_INITDIALOG:
		if( _rect.left != CW_USEDEFAULT && !(::GetWindowLong( _hWnd, GWL_STYLE )&WS_CHILD ) )
			MoveWindow( _rect.left, _rect.top, _rect.right - _rect.left, _rect.bottom - _rect.top, FALSE );
		GetWindowRect( &_orgRect );
		return EvCreate( (LPARAM)&_orgRect );
	case WM_NCDESTROY:
		GetWindowRect( &_rect );
		EvNcDestroy();
		TApp::GetApp()->DelWin( this );
		_hWnd = 0;
		return 0;
	case WM_QUERYENDSESSION:
	case WM_QUERYOPEN:
	case WM_SETCURSOR:
	case WM_NCHITTEST:
	case WM_MEASUREITEM:
	case WM_DRAWITEM:
	case WM_NOTIFY:
	case WM_CONTEXTMENU:
	case WM_HOTKEY:

	case WM_CTLCOLORBTN:
	case WM_CTLCOLORDLG:
	case WM_CTLCOLOREDIT:
	case WM_CTLCOLORLISTBOX:
	case WM_CTLCOLORMSGBOX:
	case WM_CTLCOLORSCROLLBAR:
	case WM_CTLCOLORSTATIC:
		result = TWin::WinProc( uMsg, wParam, lParam );
		SetWindowLong(DWL_MSGRESULT, result);
		return result;	
	default:
		if( uMsg < WM_USER )
		{
			TWin::WinProc( uMsg, wParam, lParam );
			return 0;
		}
		else if( uMsg >= WM_USER && uMsg <= 0x7FFF || uMsg >= 0xC000 && uMsg <= 0xFFFF )
			result = EventUser( uMsg, wParam, lParam );
		else
			result = EventSystem( uMsg, wParam, lParam );
		SetWindowLong(DWL_MSGRESULT, result);
		return	result;		
	}
	return FALSE;
}

BOOL TDlg::PreProcMsg( MSG* msg )
{
	if( _hAccel && ::TranslateAccelerator( _hWnd, _hAccel, msg ) )
		return TRUE;
	if( !_modalFlg )
		return ::IsDialogMessage( _hWnd, msg );
	return FALSE;
}

BOOL TDlg::EvSysCommand(WPARAM uCmdType, POINTS pos)
{
	return	FALSE;
}

BOOL TDlg::EvCommand(WORD wNotifyCode, WORD wID, LPARAM hwndCtl)
{
	switch (wID)
	{
	case IDOK: case IDCANCEL: case IDYES: case IDNO:
	case IDABORT: case IDIGNORE: case IDRETRY:
		EndDialog(wID);
		return	TRUE;
	}

	return	FALSE;
}

BOOL TDlg::EvQueryOpen(void)
{
	return	FALSE;
}

BOOL TDlg::EvCreate(LPARAM lParam)
{
	return	TRUE;
}

void TDlg::EndDialog(int result)
{
	if (::IsWindow(_hWnd))
	{
		if (_modalFlg)
			::EndDialog(_hWnd, result);
		else
			::DestroyWindow(_hWnd);
	}
}

int TDlg::SetDlgItem(UINT ctl_id, DWORD flags)
{
	WINDOWPLACEMENT wp;
	wp.length = sizeof(wp);

#define BIG_ALLOC 16
	if ((_maxItems % BIG_ALLOC) == 0) {
		DlgItem *p = (DlgItem *)realloc(_dlgItems, (_maxItems + BIG_ALLOC) * sizeof(DlgItem));
		if (!p) return -1;
		_dlgItems = p;
	}
	DlgItem *item = _dlgItems + _maxItems;

	item->hWnd = GetDlgItem(ctl_id);
	::GetWindowPlacement(item->hWnd, &wp);
	item->wpos.x = wp.rcNormalPosition.left;
	item->wpos.y = wp.rcNormalPosition.top;
	item->wpos.cx = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
	item->wpos.cy = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
	item->flags = flags;

	return	_maxItems++;
}

BOOL TDlg::FitDlgItems()
{
	GetWindowRect(&_rect);
	int	xdiff = (_rect.right - _rect.left) - (_orgRect.right - _orgRect.left);
	int ydiff = (_rect.bottom - _rect.top) - (_orgRect.bottom - _orgRect.top);

	HDWP	hdwp = ::BeginDeferWindowPos(_maxItems);	// MAX item number
	UINT	dwFlg = SWP_SHOWWINDOW | SWP_NOZORDER;

	for (int i=0; i < _maxItems; i++) {
		DlgItem *item = _dlgItems + i;
		DWORD	f = item->flags;

		if (f & FIT_SKIP) continue;
		int x = (f & LEFT_FIT) == LEFT_FIT ? item->wpos.x : item->wpos.x + xdiff;
		int y = (f & TOP_FIT)  == TOP_FIT  ? item->wpos.y : item->wpos.y + ydiff;
		int w = (f & X_FIT)    == X_FIT    ? item->wpos.cx + xdiff : item->wpos.cx;
		int h = (f & Y_FIT)    == Y_FIT    ? item->wpos.cy + ydiff : item->wpos.cy;

		hdwp = ::DeferWindowPos(hdwp, item->hWnd, 0, x, y, w, h, dwFlg);
	}
	EndDeferWindowPos(hdwp);

	return	TRUE;
}
